//
//  MCNNavigationBarController.swift
//  MCNNavigationBarController
//
//  Created by yhbj on 2021/9/17.
//

import UIKit

enum MCNNavStatusBarStyle: Int {
    case Default = 0x01 // 状态栏黑色
    case Light = 0x02 // 状态栏白色
}

enum MCNNavPopBlockFrom: Int {
    case BackButtonClick = 0x01 // 点击返回按钮触发pop
    case HistoryStack = 0x02 // 长按返回按钮显示历史堆栈
    case PopGesture = 0x03 // 返回手势触发pop
}

typealias leftBtnClickedBlock = ((_ btn: MCNNavItemButton) -> ())?
typealias subLeftBtnClickedBlock = ((_ btn: MCNNavItemButton) -> ())?
typealias rightBtnClickedBlock = ((_ btn: MCNNavItemButton) -> ())?
typealias subRightBtnClickedBlock = ((_ btn: MCNNavItemButton) -> ())?
typealias foldingOffsetBlock = ((_ offset: CGFloat) -> ())?
typealias foldCompletionBlock = (() -> ())?

typealias transparentGradientsChangingBlock = ((_ alpha: CGFloat) -> ())?
typealias transparentGradientsTransparentBlock = (() -> ())?
typealias transparentGradientsOpaqueBlock = (() -> ())?

class MCNXibTopConstraintModel: NSObject {
    /**
     与控制器view或safeArea的顶部约束
     */
    var constraint: NSLayoutConstraint?
    /**
     与控制器view的顶部约束的原始constant
     */
    var orgOffset: CGFloat = 0
    /**
     是否是与safeArea的顶部约束
     */
    var isToSafeArea: Bool = false
}

class MCNNavigationBarController: UIViewController, UIGestureRecognizerDelegate {
    /**
     设置左右Button的大小(宽高相等)
     */
    var mcn_navItemSize: CGFloat = 0 {
        didSet {
            mcn_navBar.mcn_itemSize = mcn_navItemSize
        }
    }

    /**
     设置Item之间的间距
     */
    var mcn_navItemMargin: CGFloat = 0 {
        didSet {
            mcn_navBar.mcn_itemMargin = mcn_navItemMargin
        }
    }

    /**
     状态栏颜色
     */
    var mcn_navStatusBarStyle: MCNNavStatusBarStyle = .Default {
        didSet {
            defaultNavStatusBarStyle = mcn_navStatusBarStyle
            if !mcn_disableAutoSetStatusBarStyle {
                let basedStatusBarAppearance = Bundle.main.object(forInfoDictionaryKey: "UIViewControllerBasedStatusBarAppearance")
                if basedStatusBarAppearance == nil || (basedStatusBarAppearance as! Bool) {
                    setNeedsStatusBarAppearanceUpdate()
                } else {
                    UIApplication.shared.setStatusBarStyle(preferredStatusBarStyle, animated: true)
                }
            }
        }
    }

    /**
     是否禁止根据mcn_navStatusBarStyle自动调整状态栏颜色，默认为否
     */
    var mcn_disableAutoSetStatusBarStyle: Bool = false

    /**
     是否隐藏ZXNavigationBar导航栏，默认为否
     */
    var mcn_hideBaseNavBar: Bool = false {
        willSet {
            if mcn_hideBaseNavBar != newValue {
                if newValue {
                    adjustNavContainerOffset(offset: 0, false)
                } else {
                    adjustNavContainerOffset(offset: getCurrentNavHeight())
                }
            }
        }
        didSet {
            mcn_navBar.isHidden = mcn_hideBaseNavBar
        }
    }

    /**
     是否显示系统导航栏，默认为否
     */
    var mcn_showSystemNavBar: Bool = false {
        didSet {
            if navigationController != nil {
                mcn_hideBaseNavBar = true
                navigationController!.navigationBar.isTranslucent = !mcn_showSystemNavBar
                navigationController!.isNavigationBarHidden = !mcn_showSystemNavBar
                checkDoAutoSysBarAlpha()
            }
        }
    }
    /**
     是否开启系统导航栏与自定义导航栏平滑过渡(务必仅当存在系统导航栏与自定义导航栏过渡时启用，非必要请勿启用，否则可能造成自定义导航栏跳动，若当前控制器显示了系统导航栏，请于当前控制器pop的上一个控制器中使用self.mcn_navEnableSmoothFromSystemNavBar = YES)
     */
    var mcn_navEnableSmoothFromSystemNavBar: Bool = false {
        didSet {
            mcn_navBar.setValue(mcn_navEnableSmoothFromSystemNavBar, forKey: "zx_navEnableSmoothFromSystemNavBar")
            UIApplication.shared.keyWindow?.backgroundColor = mcn_navBar.backgroundColor
            checkDoAutoSysBarAlpha()
        }
    }

    /**
     是否禁止Xib加载控制器情况下自动将顶部View约束下移导航栏高度，默认为否(使用Xib加载控制器时生效)
     */
    var mcn_disableNavAutoSafeLayout: Bool = false {
        didSet {
            adjustNavContainerOffset(offset: 0)
        }
    }

    /**
     禁止自动设置自定义导航栏与其相关配置，保留原有的系统导航栏（需要设置在[super viewDidLoad]之前）
     */
    var mcn_disableAutoSetCustomNavBar: Bool = false

    /**
     设置导航栏的TintColor，此属性可以将导航栏的title颜色、左右Button的文字和图片颜色修改为TintColor
     */
    var mcn_navTintColor: UIColor? {
        didSet {
            mcn_navLeftBtn?.mcn_tintColor = mcn_navTintColor
            mcn_navSubLeftBtn?.mcn_tintColor = mcn_navTintColor
            mcn_navRightBtn?.mcn_tintColor = mcn_navTintColor
            mcn_navSubRightBtn?.mcn_tintColor = mcn_navTintColor
            mcn_navTitleLabel?.textColor = mcn_navTintColor
        }
    }

    /**
     设置导航栏标题，使用self.title亦可
    */
    var mcn_navTitle: String? {
        didSet {
            mcn_navTitleLabel?.text = mcn_navTitle
        }
    }
    
    override var title: String? {
        didSet {
            mcn_navTitle = title
        }
    }

    /**
     titleView，显示在正中间的标题View，请不要在titleView直接添加自定义的titleView，如需设置自定义导航栏请使用-mcn_addCustomTitleView方法
     */
    private(set) var mcn_navTitleView: MCNNavTitleView?

    /**
     titleLabel，显示在正中间的标题Label
     */
    var mcn_navTitleLabel: MCNNavTitleLabel?
    
    /**
     设置导航栏标题颜色
     */
    var mcn_navTitleColor: UIColor? {
        didSet {
            mcn_navTitleLabel?.textColor = mcn_navTitleColor
        }
    }

    /**
     设置导航栏标题字体大小
     */
    var mcn_navTitleFontSize: CGFloat = MCNNavDefaultTitleSize {
        didSet {
            mcn_navTitleLabel?.font = UIFont.systemFont(ofSize: mcn_navTitleFontSize)
        }
    }

    /**
     设置导航栏标题字体
     */
    var mcn_navTitleFont: UIFont? {
        didSet {
            mcn_navTitleLabel?.font = mcn_navTitleFont
        }
    }

    /**
     返回按钮的图片名，若不设置则使用默认的返回按钮图片
     */
    var mcn_backBtnImageName: String? {
        didSet {
            if navigationController != nil && navigationController!.viewControllers.count > 1 && !mcn_hideBaseNavBar {
                mcn_navLeftBtn?.setImage(getBackBtnImage(), for: .normal)
            }
        }
    }

    /**
     导航栏分割线View
     */
    var mcn_navLineView: UIView?

    /**
     导航栏分割线View背景颜色
     */
    var mcn_navLineViewBackgroundColor: UIColor = MCNNavDefaultLineColor {
        didSet {
            mcn_navLineView?.backgroundColor = mcn_navLineViewBackgroundColor
        }
    }

    /**
     导航栏分割线的高度，默认为0.5
     */
    var mcn_navLineViewHeight: CGFloat = 0.5 {
        didSet {
            mcn_navBar.mcn_lineViewHeight = mcn_navLineViewHeight
        }
    }

    /**
     最左侧Button
     */
    var mcn_navLeftBtn: MCNNavItemButton?

    /**
     左侧第二个Button
     */
    var mcn_navSubLeftBtn: MCNNavItemButton?

    /**
     最右侧Button
     */
    var mcn_navRightBtn: MCNNavItemButton?

    /**
     右侧第二个Button
     */
    var mcn_navSubRightBtn: MCNNavItemButton?

    /**
     ZXNavigationBar导航栏对象
     */
    lazy var mcn_navBar: MCNNavigationBar = {
        let navBar = MCNNavigationBar()
        mcn_navTitleView = navBar.mcn_titleView
        mcn_navTitleLabel = navBar.mcn_titleLabel
        mcn_navLeftBtn = navBar.mcn_leftBtn
        mcn_navSubLeftBtn = navBar.mcn_subLeftBtn
        mcn_navRightBtn = navBar.mcn_rightBtn
        mcn_navSubRightBtn = navBar.mcn_subRightBtn
        mcn_navLineView = navBar.mcn_lineView
        mcn_navBacImageView = navBar.mcn_backImageView
        return navBar
    }()

    /**
     设置导航栏背景颜色
     */
    var mcn_navBarBackgroundColor: UIColor? {
        didSet {
            mcn_navBar.backgroundColor = mcn_navBarBackgroundColor
        }
    }

    /**
     设置导航栏背景颜色透明度(与设置为导航栏不同，此设置仅会改变导航栏背景色RGBA中的Alpha值)
     */
    var mcn_navBarBackgroundColorAlpha: CGFloat = 1 {
        didSet {
            if mcn_navBarBackgroundColorAlpha > 1 {
                mcn_navBarBackgroundColorAlpha = 1
            } else if mcn_navBarBackgroundColorAlpha < 0 {
                mcn_navBarBackgroundColorAlpha = 0
            }
            var r: CGFloat = 1, g: CGFloat = 1, b: CGFloat = 1
            if mcn_navBar.mcn_backgroundColorComponents.count > 0 {
                r = mcn_navBar.mcn_backgroundColorComponents[0]
                g = mcn_navBar.mcn_backgroundColorComponents[1]
                b = mcn_navBar.mcn_backgroundColorComponents[2]
            }
            let sel = NSSelectorFromString("privateSetBackgroundColor(backgroundColor:)")
            if mcn_navBar.responds(to: sel) {
                mcn_navBar.perform(sel, with: UIColor(red: r, green: g, blue: b, alpha: mcn_navBarBackgroundColorAlpha))
            }
        }
    }

    /**
     导航栏背景ImageView
     */
    var mcn_navBacImageView: MCNNavBackImageView?

    /**
     设置导航栏背景图片
     */
    var mcn_navBarBackgroundImage: UIImage? {
        didSet {
            mcn_navBar.mcn_backImage = mcn_navBarBackgroundImage
        }
    }

    /**
     自定义的导航栏View，是ZXNavigationBar的SubView，如需设置自定义导航栏请使用-mcn_addCustomNavBar方法
     */
    private(set) var mcn_navCustomNavBar: UIView?

    /**
     自定义的titleView，是TitleView的SubView，如需设置自定义导航栏请使用-mcn_addCustomTitleView方法
     */
    private(set) var mcn_navCustomTitleView: UIView?

    /**
     导航栏是否已被折叠，默认为否
     */
    private(set) var mcn_navIsFolded: Bool = false

    /**
     导航栏折叠动画速度
     */
    private(set) var mcn_navFoldingSpeed: Int = 0

    /**
     是否禁用全屏pop手势，若禁用，则pop触发范围为屏幕宽度的十分之一(导航控制器需为ZXNavigationBarNavigationController或继承于ZXNavigationBarNavigationController)
     */
    var mcn_disableFullScreenGesture: Bool = false {
        didSet {
            if !(navigationController != nil && navigationController!.isKind(of: MCNNavigationBarNavigationController.classForCoder())) {
                assert(false, "监听自定义手势时，您的导航控制器需为ZXNavigationBarNavigationController或继承于ZXNavigationBarNavigationController")
            } else {
                (navigationController as! MCNNavigationBarNavigationController).mcn_disableFullScreenGesture = mcn_disableFullScreenGesture
            }
        }
    }

    /**
     pop手势的触发范围比例，0-1，默认为1，即代表全屏触发(导航控制器需为ZXNavigationBarNavigationController或继承于ZXNavigationBarNavigationController)
     注意：因设置全屏返回手势响应范围与禁用全屏pop手势属于同一导航控制器，为避免此属性被其他子控制器修改，以下代码建议写在子控制器的-viewWillAppear或-viewDidAppear中
     */
    var mcn_popGestureCoverRatio: CGFloat = 1 {
        didSet {
            if !(navigationController != nil && navigationController!.isKind(of: MCNNavigationBarNavigationController.classForCoder())) {
                assert(false, "监听自定义手势时，您的导航控制器需为ZXNavigationBarNavigationController或继承于ZXNavigationBarNavigationController")
            } else {
                (navigationController as! MCNNavigationBarNavigationController).mcn_popGestureCoverRatio = mcn_popGestureCoverRatio
            }
        }
    }
    
    /**
     将所有约束为top且secondItem为控制器view或safeArea的子view约束constant设置为原始长度+导航栏高度，默认为NO，若设置为YES，将会遍历控制器view中的所有约束，对性能有一点影响（需要设置在[super viewDidLoad]之前）
     */
    var mcn_enableAdjustNavContainerAll: Bool = false
    
    /**
     自动将顶部View约束下移导航栏高度时的回调，可拦截并自定义下移距离(xib加载控制器view时生效)
     oldNavOffset:视图在xib中所设置的约束与顶部距离
     currentNavOffset:即将设置的视图与顶部的距离
     */
    var mcn_handleAdjustNavContainerOffsetBlock: ((_ oldNavOffset: CGFloat, _ currentNavOffset: CGFloat) -> (CGFloat))? {
        didSet {
            if mcn_handleAdjustNavContainerOffsetBlock != nil {
                let constraintModel = xibTopConstraintArr.first
                if constraintModel != nil {
                    adjustNavContainerOffset(offset: constraintModel!.constraint!.constant - constraintModel!.orgOffset)
                }
            }
        }
    }

    /**
     拦截点击返回事件和侧滑返回手势，若返回NO，则禁止pop;
     viewController:当前控制器
     popBlockFrom:通过什么方式(点击返回按钮或侧滑返回手势)触发pop操作
     */
    var mcn_handlePopBlock: ((_ viewController: MCNNavigationBarController, _ popBlockFrom: MCNNavPopBlockFrom) -> (Bool))?
    
    /**
     监听自定义pop手势进度(导航控制器需为ZXNavigationBarNavigationController或继承于ZXNavigationBarNavigationController)。popOffsetProgress范围为0-1，0代表即将开始pop，1代表完成pop
     注意：因手势进度监听的block属于同一导航控制器，为避免block被子控制器覆盖后失效，以下代码建议写在子控制器的-viewWillAppear或-viewDidAppear中
     */
    var mcn_handleCustomPopGesture: ((_ popOffsetProgress: CGFloat) -> ())? {
        didSet {
            if !(navigationController != nil && navigationController!.isKind(of: MCNNavigationBarNavigationController.classForCoder())) {
                assert(false, "监听自定义手势时，您的导航控制器需为ZXNavigationBarNavigationController或继承于ZXNavigationBarNavigationController")
            }
        }
    }

    /**
    pop手势是否支持多层级的手势同时触发，默认为否。若设置了此block，mcn_setPopGestureCompatibleScrollView与mcn_setPopGestureCompatibleScrollViews方法将失效
    注意：因判断是否支持多层级的手势同时触发的block属于同一导航控制器，为避免block被子控制器覆盖后失效，以下代码建议写在子控制器的-viewWillAppear或-viewDidAppear中
    */
    var mcn_popGestureShouldRecognizeSimultaneously: ((_ otherGestureRecognizer: UIGestureRecognizer) -> (Bool))? {
        didSet {
            if navigationController != nil && navigationController!.isKind(of: MCNNavigationBarNavigationController.classForCoder()) {
                (navigationController as! MCNNavigationBarNavigationController).mcn_popGestureShouldRecognizeSimultaneously = { otherGestureRecognizer in
                    return self.mcn_popGestureShouldRecognizeSimultaneously!(otherGestureRecognizer)
                }
            }
        }
    }

    /**
     导航栏固定高度
     */
    var mcn_navFixHeight: CGFloat = MCNNavBarHeight {
        didSet {
            relayoutSubviews()
            adjustNavContainerOffset(offset: getCurrentNavHeight())
        }
    }

    /**
     自定义导航栏固定frame
     */
    var mcn_navFixFrame: CGRect = .zero {
        didSet {
            if mcn_navFixFrame != .zero {
                mcn_navFixHeight = mcn_navFixFrame.height
            }
        }
    }

    /**
     导航栏frame发生改变时的回调，可在这个block中return修改后的frame
     */
    var mcn_navHandleFrameBlock: ((_ oldFrame: CGRect)->(CGRect))?
    
    /**
     导航栏历史堆栈视图
     */
    var mcn_navHistoryStackContentView: MCNNavHistoryStackContentView?

    /**
     是否显示导航栏历史堆栈视图，默认为NO
     */
    var mcn_showNavHistoryStackContentView: Bool = false

    /**
     导航栏历史堆栈视图偏离的x值，默认为0(导航栏历史堆栈视图与屏幕左侧距离默认等于leftBtn与屏幕左侧距离，此属性用于自定义在此基础上增加或减少的水平位移)
     */
    var mcn_navHistoryStackContentViewOffsetX: CGFloat = 0

    /**
     导航栏历史堆栈视图Item展示最多的数量，默认为6个，超过6个显示由栈顶往下的6个
     */
    var mcn_navHistoryStackContentViewItemMaxLength: Int = 6

    /**
     导航栏历史堆栈视图显示样式
     */
    var mcn_navHistoryStackViewStyle: MCNNavHistoryStackViewStyle?
    
    //MARK: - private
    private var setFold: Bool = false
    private var lastNavAlphe:CGFloat = 0
    private var isNavFoldAnimating: Bool = false
    private var doAutoSysBarAlphe: Bool = false
    private var orgWindowColor: UIColor?
    private var displayLink: CADisplayLink?
    private var offsetBlock: foldingOffsetBlock?
    private var completionBlock: foldCompletionBlock?
    private var isInLeftBtnTouchesBegan: Bool = false
    private var xibTopConstraintArr: [MCNXibTopConstraintModel] = []
    
    private var defaultNavStatusBarStyle: MCNNavStatusBarStyle = .Default
    
    //MARK: - function
    
    override func viewDidLoad() {
        super.viewDidLoad()
        mcn_navFixHeight = -1
        mcn_navFixFrame = .zero
        mcn_navHistoryStackContentViewItemMaxLength = MCNNavHistoryStackViewItemMaxLength
        if navigationController != nil && !mcn_hideBaseNavBar && !mcn_disableAutoSetCustomNavBar {
            initNavBar()
            setAutoBack()
        }
        checkDoAutoSysBarAlpha()
        hanldeCustomPopGesture()
    }
    
    private func initNavBar() {
        view.addSubview(mcn_navBar)
        view.bringSubview(toFront: mcn_navBar)
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.init(uptimeNanoseconds: UInt64(CGFloat.leastNonzeroMagnitude * CGFloat(NSEC_PER_SEC)))) {
            self.view.bringSubview(toFront: self.mcn_navBar)
        }
        mcn_navTitleLabel?.text = mcn_navTitle
        adjustNavContainerOffset(offset: getCurrentNavHeight())
        relayoutSubviews()
    }
    
    private func setAutoBack() {
        if navigationController != nil && navigationController!.viewControllers.count > 1 {
            let backImg = getBackBtnImage()
            mcn_navLeftBtn!.setImage(backImg, for: .normal)
            self.mcn_leftClickedBlock { [weak self] btn in
                guard let sSelf = self else { return }
                if !(sSelf.mcn_handlePopBlock != nil && !sSelf.mcn_handlePopBlock!(sSelf, MCNNavPopBlockFrom.BackButtonClick)) {
                    sSelf.navigationController?.popViewController(animated: true)
                    sSelf.mcn_hideNavHistoryStackView()
                }
            }
            mcn_navLeftBtn?.isUserInteractionEnabled = true
            mcn_navLeftBtn?.mcn_touchesBeganBlock = { [weak self] in
                guard let sSelf = self else { return }
                sSelf.isInLeftBtnTouchesBegan = true
                DispatchQueue.main.asyncAfter(deadline: DispatchTime.init(uptimeNanoseconds: UInt64(CGFloat.leastNonzeroMagnitude * CGFloat(NSEC_PER_SEC)))) {
                    if sSelf.isInLeftBtnTouchesBegan {
                        sSelf.mcn_showNavHistoryStackView()
                    }
                    sSelf.isInLeftBtnTouchesBegan = false
                }
            }
            mcn_navLeftBtn?.mcn_touchesEndBlock = { [weak self] in
                guard let sSelf = self else { return }
                sSelf.isInLeftBtnTouchesBegan = false
            }
            let leftBtnPanGestureRecognizer = UIGestureRecognizer(target: self, action: #selector(handleLeftBtnPanGesture(sender:)))
            mcn_navLeftBtn?.addGestureRecognizer(leftBtnPanGestureRecognizer)
        }
    }
    
    private func adjustNavContainerOffset(offset: CGFloat, _ checkSafeArea: Bool = true) {
        if mcn_disableAutoSetCustomNavBar {
            return
        }
        if xibTopConstraintArr.count > 0 {
            for constraintModel in xibTopConstraintArr {
                updateTopConstraint(constraintModel: constraintModel, offset: offset, checkSafeArea: checkSafeArea)
            }
            return
        }
        let constraintArr = view.constraints
        xibTopConstraintArr.removeAll()
        for constraint in constraintArr {
            if constraint.firstAttribute == .top {
                let secondItem = constraint.secondItem
                var secondView: UIView?
                var isToSafeArea = true
                if secondItem != nil && secondItem!.isKind(of: UILayoutGuide.classForCoder()) {
                    secondView = (secondItem! as! UILayoutGuide).owningView
                }
                if secondItem != nil && secondItem!.isKind(of: UIView.classForCoder()) {
                    secondView = secondItem as? UIView
                    isToSafeArea = false
                }
                if secondView == nil || view == secondView! {
                    let constraintModel = MCNXibTopConstraintModel()
                    constraintModel.orgOffset = constraint.constant
                    constraintModel.constraint = constraint
                    constraintModel.isToSafeArea = isToSafeArea
                    updateTopConstraint(constraintModel: constraintModel, offset: offset, checkSafeArea: checkSafeArea)
                    xibTopConstraintArr.append(constraintModel)
                    if !mcn_enableAdjustNavContainerAll {
                        return
                    }
                }
            }
        }
    }
    
    private func updateRopConstraint(constraintModel: MCNXibTopConstraintModel, offset: CGFloat, checkSafeArea: Bool) {
        if mcn_disableAutoSetCustomNavBar {
            return
        }
        var oSet = offset
        if mcn_disableNavAutoSafeLayout {
            oSet = 0
        }
        var orgNavOffset = constraintModel.orgOffset
        var handleOffset = orgNavOffset + oSet
        if mcn_handleAdjustNavContainerOffsetBlock != nil {
            handleOffset = mcn_handleAdjustNavContainerOffsetBlock!(orgNavOffset, orgNavOffset - oSet)
        }
        if constraintModel.isToSafeArea && checkSafeArea {
            if #available(iOS 11.0, *) {
                handleOffset = handleOffset - MCNMainWindow.safeAreaInsets.top
            }
        }
        constraintModel.constraint?.constant = handleOffset
    }
    
    //MARK: - 开启displaylink
    private func startDisplayLink() {
        displayLink = CADisplayLink(target: self, selector: #selector(updateNavFoldingFrame(displayLink:)))
        displayLink?.add(to: RunLoop.current, forMode: RunLoopMode.commonModes)
    }
    
    private func relayoutSubviews() {
        if mcn_navFixFrame != .zero {
            mcn_navBar.frame = mcn_navFixFrame
        } else {
            if mcn_navIsFolded {
                mcn_navBar.frame = CGRect(x: 0, y: 0, width: MCNScreenWidth, height: MCNIPhoneAppStatusBarHeight())
            } else {
                mcn_navBar.frame = CGRect(x: 0, y: 0, width: MCNScreenWidth, height: getCurrentNavHeight())
            }
        }
        if mcn_navHandleFrameBlock != nil {
            mcn_navBar.frame = mcn_navHandleFrameBlock!(mcn_navBar.frame)
        }
    }
    
    @objc func updateNavFoldingFrame(displayLink: CADisplayLink) {
        isNavFoldAnimating = true
        if setFold {
            if mcn_navBar.mcn_height > MCNAppStutsBarHeight {
                if mcn_navBar.mcn_height - CGFloat(mcn_navFoldingSpeed) < 0 {
                    mcn_navBar.mcn_height = 0
                } else {
                    mcn_navBar.mcn_height -= CGFloat(mcn_navFoldingSpeed)
                }
                for constraintModel in xibTopConstraintArr {
                    constraintModel.constraint?.constant -= CGFloat(mcn_navFoldingSpeed)
                }
                if offsetBlock != nil {
                    offsetBlock!!((-CGFloat(mcn_navFoldingSpeed)))
                }
                setAlphaOfNavSubViews(alpha: (mcn_navBar.mcn_height - MCNAppStutsBarHeight) / (getCurrentNavHeight() - MCNAppStutsBarHeight))
            } else {
                isNavFoldAnimating = false
                self.displayLink!.invalidate()
                self.displayLink = nil
                mcn_navIsFolded = setFold
                if completionBlock != nil {
                    completionBlock!!()
                }
                setAlphaOfNavSubViews(alpha: 0)
                relayoutSubviews()
            }
        } else {
            if mcn_navBar.mcn_height < getCurrentNavHeight() {
                mcn_navBar.mcn_height += CGFloat(mcn_navFoldingSpeed)
                for constraintModel in xibTopConstraintArr {
                    constraintModel.constraint?.constant += CGFloat(mcn_navFoldingSpeed)
                }
                if offsetBlock != nil {
                    offsetBlock!!(CGFloat(mcn_navFoldingSpeed))
                }
                setAlphaOfNavSubViews(alpha: (mcn_navBar.mcn_height - MCNAppStutsBarHeight) / (getCurrentNavHeight() - MCNAppStutsBarHeight))
            } else {
                isNavFoldAnimating = false
                self.displayLink!.invalidate()
                self.displayLink = nil
                mcn_navIsFolded = setFold
                if completionBlock != nil {
                    completionBlock!!()
                }
                setAlphaOfNavSubViews(alpha: 1)
                relayoutSubviews()
            }
        }
    }
    
    private func setAlphaOfNavSubViews(alpha: CGFloat) {
        for subview in mcn_navBar.subviews {
            subview.alpha = alpha
        }
    }
    
    private func getCurrentNavHeight() -> CGFloat {
        if mcn_navFixHeight == -1 {
            return MCNNavBarHeight
        }
        return CGFloat(mcn_navFixHeight)
    }
    
    private func getBackBtnImage() -> UIImage {
        var backImg: UIImage?
        if mcn_backBtnImageName != nil && mcn_backBtnImageName!.count > 0 {
            backImg = UIImage(named: mcn_backBtnImageName!)
        }
        if backImg == nil {
            backImg = UIImage.mcn_imageFromBundle(imageName: "back_icon")
        }
        return backImg!
    }
    
    //MARK: - 刷新导航状态
    private func refNavStatus(fromWillAppear: Bool) {
        if !mcn_navEnableSmoothFromSystemNavBar || !fromWillAppear {
            navigationController?.isNavigationBarHidden = !mcn_showSystemNavBar
        }
        if mcn_navEnableSmoothFromSystemNavBar {
            if !mcn_showSystemNavBar {
                navigationController?.navigationBar.isTranslucent = true
            } else {
                navigationController?.navigationBar.isTranslucent = false
            }
        }
    }
    
    //MARK: - 监听自定义pop手势进度，导航控制器需为ZXNavigationBarNavigationController或继承于ZXNavigationBarNavigationController
    private func hanldeCustomPopGesture() {
        if navigationController != nil && navigationController!.isKind(of: MCNNavigationBarNavigationController.classForCoder()) {
            let nav = navigationController as! MCNNavigationBarNavigationController
            nav.mcn_handleCustomPopGesture = { [weak self] currentViewController, popOffsetProgess in
                guard let sSelf = self else { return }
                if currentViewController == sSelf {
                    if sSelf.mcn_handleCustomPopGesture != nil {
                        sSelf.mcn_handleCustomPopGesture!(popOffsetProgess)
                    }
                    if sSelf.doAutoSysBarAlphe {
                        nav.navigationBar.alpha = 1 - popOffsetProgess
                        if nav.navigationBar.alpha == 0 {
                            UIApplication.shared.keyWindow?.backgroundColor = sSelf.orgWindowColor
                        } else {
                            if UIApplication.shared.keyWindow?.backgroundColor != sSelf.orgWindowColor {
                                sSelf.orgWindowColor = UIApplication.shared.keyWindow?.backgroundColor
                                if nav.navigationBar.backgroundColor != nil {
                                    UIApplication.shared.keyWindow?.backgroundColor = nav.navigationBar.backgroundColor!
                                } else {
                                    UIApplication.shared.keyWindow?.backgroundColor = .white
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    private func updateTopConstraint(constraintModel: MCNXibTopConstraintModel, offset: CGFloat, checkSafeArea: Bool) {
        if mcn_disableAutoSetCustomNavBar {
            return
        }
        var mcn_offset = offset
        if mcn_disableNavAutoSafeLayout {
            mcn_offset = 0
        }
        var orgNavOffset = constraintModel.orgOffset
        var handleOffset = orgNavOffset + mcn_offset
        if mcn_handleAdjustNavContainerOffsetBlock != nil {
            handleOffset = mcn_handleAdjustNavContainerOffsetBlock!(orgNavOffset, orgNavOffset + mcn_offset)
        }
        if constraintModel.isToSafeArea && checkSafeArea {
            if #available(iOS 11.0, *) {
                handleOffset = handleOffset - MCNMainWindow.safeAreaInsets.top
            }
        }
        constraintModel.constraint?.constant = handleOffset
    }
    
    private func checkDoAutoSysBarAlpha() {
        let previousViewController = getPreviousViewController()
        var doAutoSysBarAlphe = false
        if previousViewController != nil && (previousViewController!.isKind(of: MCNNavigationBarController.classForCoder()) || previousViewController!.isKind(of: MCNNavigationBarTableViewController.classForCoder())) {
            if (previousViewController!.value(forKey: "zx_navEnableSmoothFromSystemNavBar") as! Bool) && mcn_showSystemNavBar {
                doAutoSysBarAlphe = true
            }
        }
        self.doAutoSysBarAlphe = doAutoSysBarAlphe
    }
    
    //MARK: - 隐藏历史堆栈
    private func mcn_hideNavHistoryStackView() {
        if mcn_navHistoryStackContentView != nil {
            mcn_navHistoryStackContentView!.mcn_hide()
            mcn_navHistoryStackContentView = nil
        }
    }
    
    @objc func handleLeftBtnPanGesture(sender: UIGestureRecognizer) {
        if mcn_navHistoryStackContentView != nil {
            let point = sender.location(in: sender.view)
            let convertedPoint = mcn_navHistoryStackContentView?.mcn_historyStackView.convert(point, from: sender.view)
            mcn_navHistoryStackContentView!.handlePanGesture(point: convertedPoint!)
        }
        if sender.state == .ended {
            mcn_navHistoryStackContentView!.handlePanGestureEnd()
        }
    }
    
    /**
     设置最左侧Button的图片和点击回调

     @param imgName 图片名字
     @param clickBlock 点击回调
     */
    func mcn_setLeftBtn(imageName: String, clickedBlock: leftBtnClickedBlock) {
        mcn_navLeftBtn?.setImage(UIImage(named: imageName), for: .normal)
        mcn_navBar.mcn_leftBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     设置左侧第二个Button的图片和点击回调

     @param imgName 图片名字
     @param clickBlock 点击回调
     */
    func mcn_setSubLeftBtn(imageName: String, clickedBlock: subLeftBtnClickedBlock) {
        mcn_navSubLeftBtn?.setImage(UIImage(named: imageName), for: .normal)
        mcn_navBar.mcn_leftBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     设置最右侧Button的图片和点击回调

     @param imgName 图片名字
     @param clickBlock 点击回调
     */
    func mcn_setRightBtn(imageName: String, clickedBlock: rightBtnClickedBlock) {
        mcn_navRightBtn?.setImage(UIImage(named: imageName), for: .normal)
        mcn_navBar.mcn_rightBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     设置右侧第二个Button的图片和点击回调(此按钮您支持设置图片)

     @param imgName 图片名字
     @param clickBlock 点击回调
     */
    func mcn_setSubRightBtn(imageName: String, clickedBlock: subRightBtnClickedBlock) {
        mcn_navSubRightBtn?.setImage(UIImage(named: imageName), for: .normal)
        mcn_navBar.mcn_subRightBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     设置最左侧Button的文字和点击回调

     @param btnText 按钮文字
     @param clickBlock 点击回调
     */
    func mcn_setleftBtn(btnText: String, clickedBlock: leftBtnClickedBlock) {
        mcn_navLeftBtn?.setTitle(btnText, for: .normal)
        mcn_navBar.mcn_leftBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     设置左侧第二个Button的文字和点击回调

     @param btnText 按钮文字
     @param clickBlock 点击回调
     */
    func mcn_setSubLeftBtn(btnText: String, clickedBlock: subLeftBtnClickedBlock) {
        mcn_navSubLeftBtn?.setTitle(btnText, for: .normal)
        mcn_navBar.mcn_subLeftBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     设置右侧第二个Button的文字和点击回调

     @param btnText 按钮文字
     @param clickBlock 点击回调
     */
    func mcn_setSubRightBtn(btnText: String, clickedBlock: subRightBtnClickedBlock) {
        mcn_navSubRightBtn?.setTitle(btnText, for: .normal)
        mcn_navBar.mcn_subRightBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     设置最右侧Button的文字和点击回调

     @param btnText 按钮文字
     @param clickBlock 点击回调
     */
    func mcn_setRightBtn(btnText: String, clickedBlock: rightBtnClickedBlock) {
        mcn_navRightBtn?.setTitle(btnText, for: .normal)
        mcn_navBar.mcn_rightBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     设置最左侧Button的图片Url和点击回调

     @param imgUrlStr 图片Url
     @param placeholderImgName 占位图名称
     @param clickBlock 点击回调
     */
    func mcn_setLeftBtn(imgUrlString: String, placeholderImageName: String, clickedBlock: leftBtnClickedBlock) {
        setNavItemBtn(btn: mcn_navLeftBtn!, imgUrl: imgUrlString, placeholderImgName: placeholderImageName)
        mcn_navBar.mcn_leftBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     设置左侧第二个Button的图片Url和点击回调

     @param imgUrlStr 图片Url
     @param placeholderImgName 占位图名称
     @param clickBlock 点击回调
     */
    func mcn_setSubLeftBtn(imgUrlString: String, placeholderImageName: String, clickedBlock: subLeftBtnClickedBlock) {
        setNavItemBtn(btn: mcn_navSubLeftBtn!, imgUrl: imgUrlString, placeholderImgName: placeholderImageName)
        mcn_navBar.mcn_subLeftBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     设置最右侧Button的图片Url和点击回调

     @param imgUrlStr 图片Url
     @param placeholderImgName 占位图名称
     @param clickBlock 点击回调
     */
    func mcn_setRightBtn(imgUrlString: String, placeholderImageName: String, clickedBlock: rightBtnClickedBlock) {
        setNavItemBtn(btn: mcn_navRightBtn!, imgUrl: imgUrlString, placeholderImgName: placeholderImageName)
        mcn_navBar.mcn_rightBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     设置右侧第二个Button的图片Url和点击回调

     @param imgUrlStr 图片Url
     @param placeholderImgName 占位图名称
     @param clickBlock 点击回调
     */
    func mcn_setSubRightBtn(imgUrlString: String, placeholderImageName: String, clickedBlock: subRightBtnClickedBlock) {
        setNavItemBtn(btn: mcn_navSubRightBtn!, imgUrl: imgUrlString, placeholderImgName: placeholderImageName)
        mcn_navBar.mcn_subRightBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     设置最左侧按钮图片和点击回调

     @param img 图片
     @param clickBlock 点击回调
     */
    func mcn_setLeftBtn(img: UIImage, clickedBlock: leftBtnClickedBlock) {
        mcn_navLeftBtn?.setImage(img, for: .normal)
        mcn_navBar.mcn_leftBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }
    
    /**
     设置最左侧按钮图片和点击回调

     @param img 图片
     @param clickBlock 点击回调
     */
    func mcn_setSubLeftBtn(img: UIImage, clickedBlock: leftBtnClickedBlock) {
        mcn_navSubLeftBtn?.setImage(img, for: .normal)
        mcn_navBar.mcn_subLeftBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     设置右侧按钮图片和点击回调

     @param img 图片
     @param clickBlock 点击回调
     */
    func mcn_setRightBtn(img: UIImage, clickedBlock: rightBtnClickedBlock) {
        mcn_navRightBtn?.setImage(img, for: .normal)
        mcn_navBar.mcn_rightBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     设置右侧按钮图片和点击回调

     @param img 图片
     @param clickBlock 点击回调
     */
    func mcn_setSubRightBtn(img: UIImage, clickedBlock: subRightBtnClickedBlock) {
        mcn_navSubRightBtn?.setImage(img, for: .normal)
        mcn_navBar.mcn_subRightBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     最左侧Button的点击回调

     @param clickBlock 点击回调
     */
    func mcn_leftClickedBlock(clickedBlock: leftBtnClickedBlock) {
        mcn_navBar.mcn_leftBtnClickedBlock = { btn in
            if clickedBlock != nil {
                clickedBlock!(btn)
            }
        }
    }

    /**
     左侧第二个Button的点击回调

     @param clickBlock 点击回调
     */
    func mcn_subLeftClickedBlock(clickBlock: subLeftBtnClickedBlock) {
        mcn_navBar.mcn_subLeftBtnClickedBlock = { btn in
            if clickBlock != nil {
                clickBlock!(btn)
            }
        }
    }

    /**
     最右侧Button的点击回调

     @param clickBlock 点击回调
     */
    func mcn_rightClickedBlock(clickBlock: rightBtnClickedBlock) {
        mcn_navBar.mcn_rightBtnClickedBlock = { btn in
            if clickBlock != nil {
                clickBlock!(btn)
            }
        }
    }
    
    /**
     右侧第二个Button的点击回调

     @param clickBlock 点击回调
     */
    func mcn_subRightClickedBlock(clickBlock: subRightBtnClickedBlock) {
        mcn_navBar.mcn_subRightBtnClickedBlock = { btn in
            if clickBlock != nil {
                clickBlock!(btn)
            }
        }
    }

    /**
     添加自定义导航栏

     @param navBar 自定义导航栏View
     */
    func mcn_addCustomNavBar(navBar: UIView) {
        if mcn_navCustomNavBar != nil {
            mcn_navCustomNavBar!.removeFromSuperview()
        }
        mcn_navBar.addSubview(navBar)
        mcn_navCustomNavBar = navBar
        mcn_navBar.mcn_customNavBar = navBar
    }

    /**
     设置大小标题效果

     @param title 大标题
     @param subTitle 小标题
     */
    func mcn_setMulti(title: String, subTitle: String) {
        mcn_navBar.mcn_setMulti(title: title, subTitle: subTitle)
    }

    /**
     设置大小标题效果

     @param title 大标题
     @param subTitle 小标题
     @param subTitleFont 小标题字体
     @param subTitleColor 小标题颜色
     */
    func mcn_setMulti(title: String, subTitle: String, subTitleFont: UIFont, subTitleTextColor: UIColor) {
        mcn_navBar.mcn_setMulti(title: title, subTitle: subTitle, subTitleFont: subTitleFont, subTitleTextColor: subTitleTextColor)
    }

    /**
     设置导航栏背景渐变(颜色渐变从fromColor到toColor)

     @param fromColor 起止颜色
     @param toColor 终止颜色
     */
    func mcn_setNavGradientBac(fromColor: UIColor, toColor: UIColor) {
        let gradientLayer = CAGradientLayer()
        gradientLayer.startPoint = CGPoint(x: 0, y: 0)
        gradientLayer.endPoint = CGPoint(x: 1, y: 0)
        gradientLayer.colors = [fromColor, toColor]
        mcn_navBar.mcn_gradientLayer = gradientLayer
    }

    /**
     移除导航栏渐变背景
     */
    func mcn_removeNavGradientBac() {
        mcn_navBar.mcn_gradientLayer = nil
    }

    /**
     添加自定义的TitleView

     @param customTitleView 自定义的TitleView
     */
    func mcn_addCustomTitleView(customTitleView: UIView) {
        if mcn_navCustomTitleView != nil {
            mcn_navCustomTitleView!.removeFromSuperview()
        }
        mcn_navTitleLabel?.text = ""
        mcn_navTitleView?.addSubview(customTitleView)
        mcn_navCustomTitleView = customTitleView
        mcn_navBar.mcn_customTitleView = customTitleView
    }
    
    /**
     设置可伸缩折叠式导航栏

     @param folded 是否折叠，为否时即为展开
     @param speed 折叠效果动画速度，1-6，建议3
     @param offsetBlock 折叠动画导航栏位移回调，当控制器使用frame布局时，用于在导航栏高度更改时，同时设置导航栏下方视图的frame，此时获取到的offset就是导航栏实时相较自身位移距离
     @param completionBlock 折叠动画结束回调
     */
    func mcn_setNav(folded: Bool, speed: Int, offsetBlock: foldingOffsetBlock, completionBlock: foldCompletionBlock) {
        self.offsetBlock = offsetBlock
        self.completionBlock = completionBlock
        if speed > 0 && speed < 6 {
            mcn_navFoldingSpeed = speed
        } else {
            mcn_navFoldingSpeed = 3
        }
        if setFold != folded {
            setFold = folded
            startDisplayLink()
        } else {
            setFold = folded
        }
    }
    
    /// 通过ScrollView滚动自动控制导航栏透明效果(类似微博热搜页面)
    /// @param scrollView 滚动控制的scrollView，tableView或collectionView
    /// @param fullChangeHeight scrollView.contentOffset.y达到fullChangeHeight时，导航栏变为完全不透明
    /// @param changeLimitNavAlphe 当导航栏透明度达到changeLimitNavAlphe时，将触发opaqueBlock，通知控制器设置导航栏不透明时的效果
    /// @param transparentBlock 导航栏切换到透明状态时的回调（默认透明度0.7为临界点）
    /// @param opaqueBlock 导航栏切换到不透明状态时的回调（默认透明度0.7为临界点）
    func mcn_setNavTransparentGradients(scrollView: UIScrollView, fullChangeHeight: CGFloat, changeLimitNavAlphe: CGFloat, transparentBlock: transparentGradientsTransparentBlock, opaqueBlock: transparentGradientsOpaqueBlock) {
        mcn_setNavTransparentGradients(scrollView: scrollView, fullChangeHeight: fullChangeHeight, changeLimitNavAlphe: changeLimitNavAlphe, changeBlock: nil, transparentBlock: transparentBlock, opaqueBlock: opaqueBlock)
    }
    
    /// 通过ScrollView滚动自动控制导航栏透明效果(类似微博热搜页面)
    /// @param scrollView 滚动控制的scrollView，tableView或collectionView
    /// @param fullChangeHeight scrollView.contentOffset.y达到fullChangeHeight时，导航栏变为完全不透明
    /// @param changeLimitNavAlphe 当导航栏透明度达到changeLimitNavAlphe时，将触发opaqueBlock，通知控制器设置导航栏不透明时的效果
    /// @param transparentBlock 导航栏切换到透明状态时的回调（默认透明度0.7为临界点）
    /// @param opaqueBlock 导航栏切换到不透明状态时的回调（默认透明度0.7为临界点）
    func mcn_setNavTransparentGradients(scrollView: UIScrollView, fullChangeHeight: CGFloat, changeLimitNavAlphe: CGFloat, changeBlock: transparentGradientsChangingBlock?, transparentBlock: transparentGradientsTransparentBlock, opaqueBlock: transparentGradientsOpaqueBlock) {
        var changeLimitAlphe = changeLimitNavAlphe
        if changeLimitAlphe < 0 || changeLimitAlphe > 1 {
            changeLimitAlphe = 0.7
        }
        let offsetY = scrollView.contentOffset.y
        var navAlphe = offsetY / fullChangeHeight
        navAlphe = navAlphe < 0 ? 0 : navAlphe > 1 ? 1 : navAlphe
        if lastNavAlphe >= 0 && lastNavAlphe <= 1 {
            if changeBlock != nil {
                changeBlock!!(navAlphe)
            } else {
                mcn_navBarBackgroundColorAlpha = navAlphe
            }
        }
        if navAlphe > changeLimitNavAlphe && lastNavAlphe <= changeLimitNavAlphe {
            if opaqueBlock != nil {
                opaqueBlock!()
            }
        }
        if navAlphe < changeLimitNavAlphe && lastNavAlphe >= changeLimitNavAlphe {
            if transparentBlock != nil {
                transparentBlock!()
            }
        }
        lastNavAlphe = navAlphe
    }

    /// 设置与pop手势冲突的scrollView数组以兼容pop手势与scrollView手势
    /// @param scrollViewArr scrollView数组
    /// 注意：因判断是否支持多层级的手势同时触发的block属于同一导航控制器，为避免block被子控制器覆盖后失效，以下代码建议写在子控制器的-viewWillAppear或-viewDidAppear中
    func mcn_setPopGestureCompatible(scrollViewArr: [UIScrollView]?) {
        if scrollViewArr != nil && scrollViewArr!.count > 0 {
            if navigationController == nil {
                assert(false, "当前控制器不是导航控制器的子控制器！")
                return
            }
            let scrollArr = scrollViewArr!
            let navGestureArray = navigationController!.view.gestureRecognizers
            if navigationController!.isKind(of: MCNNavigationBarNavigationController.classForCoder()) {
                let navController = navigationController! as! MCNNavigationBarNavigationController
                for gestureRecognizer in navGestureArray! {
                    if gestureRecognizer == navController.mcn_popGestureRecognizer {
                        navController.mcn_popGestureShouldRecognizeSimultaneously = { otherGestureRecognizer in
                            for scrollView in scrollArr {
                                scrollView.bounces = false
                                if otherGestureRecognizer.view != scrollView {
                                    continue
                                }
                                return scrollView.contentOffset.x <= 0
                            }
                            return false
                        }
                        break
                    }
                }
            } else {
                for gestureRecognizer in navGestureArray! {
                    if gestureRecognizer.isKind(of: UIScreenEdgePanGestureRecognizer.classForCoder()) {
                        for scrollView in scrollArr {
                            scrollView.panGestureRecognizer.require(toFail: gestureRecognizer)
                        }
                        break
                    }
                }
            }
        }
    }

    /// 设置与pop手势冲突的scrollView以兼容pop手势与scrollView手势
    /// @param scrollView scrollView
    /// 注意：因判断是否支持多层级的手势同时触发的block属于同一导航控制器，为避免block被子控制器覆盖后失效，以下代码建议写在子控制器的-viewWillAppear或-viewDidAppear中
    func mcn_setPopGestureCompatible(scrollView: UIScrollView?) {
        if scrollView != nil {
            mcn_setPopGestureCompatible(scrollViewArr: [scrollView!])
        }
    }

    /// 手动显示导航栏历史堆栈view
    func mcn_showNavHistoryStackView() {
        if navigationController != nil && mcn_showNavHistoryStackContentView {
            if mcn_handlePopBlock != nil && !mcn_handlePopBlock!(self, .HistoryStack) {
                return
            }
            let view = MCNNavHistoryStackContentView()
            var historyStackArray: [MCNNavHistoryStackModel] = []
            var viewControllersArr = navigationController!.viewControllers
            if viewControllersArr.count > 0 {
                viewControllersArr.removeLast()
                viewControllersArr = viewControllersArr.reversed()
                if viewControllersArr.count > mcn_navHistoryStackContentViewItemMaxLength {
                    viewControllersArr.removeSubrange(mcn_navHistoryStackContentViewItemMaxLength..<viewControllersArr.count)
                }
                for viewController in viewControllersArr {
                    let historyStackModel = MCNNavHistoryStackModel()
                    var title = viewController.title
                    if viewController.isKind(of: MCNNavigationBarController.classForCoder()) {
                        title = (viewController as! MCNNavigationBarController).mcn_navTitleLabel?.text
                    }
                    if viewController.isKind(of: MCNNavigationBarTableViewController.classForCoder()) {
                        title = (viewController as! MCNNavigationBarTableViewController).mcn_navTitleLabel?.text
                    }
                    historyStackModel.title = title
                    historyStackModel.viewController = viewController
                    historyStackArray.append(historyStackModel)
                }
                if historyStackArray.count > 0 {
                    view.mcn_historyStackArray = historyStackArray
                    view.mcn_historyStackViewLeft = mcn_navLeftBtn!.mcn_x + mcn_navHistoryStackContentViewOffsetX
                    view.mcn_historyStackViewStyle = mcn_navHistoryStackViewStyle
                    mcn_navHistoryStackContentView = view.mcn_show()
                }
            }
        }
    }
    
    //MARK: - private
    private func setNavItemBtn(btn: UIButton, imgUrl: String, placeholderImgName: String) {
        btn.setImage(UIImage(named: placeholderImgName), for: .normal)
        print("项目中没有继承加载网络图片的库，只会加载占位图片")
    }
    
    //MARK: - other
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if !mcn_disableAutoSetCustomNavBar {
            refNavStatus(fromWillAppear: true)
            if #available(iOS 11.0, *) {
                UIScrollView.appearance().contentInsetAdjustmentBehavior = .never
            } else {
                automaticallyAdjustsScrollViewInsets = false
            }
        }
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        if mcn_disableAutoSetCustomNavBar {
            return
        }
        if mcn_showSystemNavBar {
            navigationController!.isNavigationBarHidden = false
        }
        navigationController!.navigationBar.isTranslucent = false
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        if mcn_navEnableSmoothFromSystemNavBar && !mcn_disableAutoSetCustomNavBar {
            refNavStatus(fromWillAppear: false)
        }
        if navigationController != nil && !(navigationController!.isKind(of: MCNNavigationBarNavigationController.classForCoder())) {
            navigationController!.interactivePopGestureRecognizer?.delegate = self
            navigationController!.interactivePopGestureRecognizer?.isEnabled = navigationController!.viewControllers.first != self
        }
        if navigationController != nil {
            navigationController!.interactivePopGestureRecognizer?.isEnabled = false
        }
        if navigationController != nil && navigationController!.isKind(of: MCNNavigationBarNavigationController.classForCoder()) {
            (navigationController as! MCNNavigationBarNavigationController).updateTopViewController(viewController: self)
        }
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        if mcn_disableAutoSetCustomNavBar {
            return
        }
        if !isNavFoldAnimating {
            relayoutSubviews()
        }
    }
    
    override var preferredStatusBarStyle: UIStatusBarStyle {
        get {
            if mcn_disableAutoSetStatusBarStyle {
                return super.preferredStatusBarStyle
            }
            let statusBarStyle = mcn_navStatusBarStyle
            if statusBarStyle == .Light {
                return .lightContent
            } else {
                return .default
            }
        }
    }
    
    //MARK: - UIGestureRecognizerDelegate
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        if mcn_handlePopBlock != nil {
            return mcn_handlePopBlock!(self, .PopGesture)
        }
        return true
    }
    
    //MARK: - 点击了系统导航栏返回按钮处理
    func mcn_navSystemBarPopHandle() -> Bool {
        if doAutoSysBarAlphe {
            orgWindowColor = UIApplication.shared.keyWindow?.backgroundColor
            if navigationController!.navigationBar.backgroundColor != nil {
                UIApplication.shared.keyWindow?.backgroundColor =  navigationController!.navigationBar.backgroundColor
            } else {
                UIApplication.shared.keyWindow?.backgroundColor = .white
            }
            UIView.animate(withDuration: 0.2) {
                self.navigationController!.navigationBar.alpha = 0
            } completion: { _ in
                UIApplication.shared.keyWindow?.backgroundColor = self.orgWindowColor
            }
        }
        if mcn_handlePopBlock != nil {
            return mcn_handlePopBlock!(self, .BackButtonClick)
        }
        return true
    }
    
    func getPreviousViewController() -> UIViewController? {
        if navigationController != nil && navigationController!.childViewControllers.count > 1 {
            return navigationController!.childViewControllers[navigationController!.childViewControllers.count - 2]
        }
        return nil
    }
}
